﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.Timers;
using System.Media;
using System.Windows.Media.Animation;
using com.skype.api;
using System.Threading;
using System.Diagnostics;
using Hugo.UIPages;
using Hugo.UIOptions;

namespace Hugo
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        Label dayLabel;
        Label timeLabel;

        //Boolean isSleeping;
        Boolean useHandCursor = true;

        HandCursor cursor;

        int sleepTimerAmount = 1000 * 60 * 60 * 3; // 3hrs

        public BackgroundCanvas bgCanvas;
        public Canvas mainCanvas { get; set; }
        public Canvas pageParentCanvas { get; set; }

        static Queue<NotificationUIPage> notificationQueue = new Queue<NotificationUIPage>();

        static Stack<UIPage> pageStack = new Stack<UIPage>();
        static UIPage root;
        static UIPage inbox;
        static UIPage help;
        static UIPage screenSaver;

        private static Action EmptyDelegate = delegate() { };

        private static MainWindow instance;

        public static MainWindow getInstance()
        {
            return instance;
        }

        public MainWindow()
        {
            if (instance == null)
            {
                instance = this;
            }

            InitializeComponent();
            init();

            //new Hugo.Gesture.GestureTranslator(this);
            //GestureWindow gw = new GestureWindow();
            //gw.Show();

            restartSleepTimer();
        }

        System.Windows.Point lastCursor;

        private void updateHandCursorTimerTick(Object sender, EventArgs e)
        {

            System.Windows.Point p = cursor.getPosition();

            if (lastCursor != null && Math.Max(p.X - lastCursor.X, p.Y - lastCursor.Y) > 10)
            {
                //wakeUp();
                restartSleepTimer();
            }

            lastCursor = p;

            //if (!isSleeping)
            //{
                this.setCursorPositionMaster(p);
            //}
        }

        private void init()
        {
            if (GlobalSettings.isUsingSkype)
            {
                Communicate.getInstance();
            }
          
            initCanvases();

            initTime();
            initPages();

            if (GlobalSettings.isUsingKinect && GlobalSettings.isUsingVoice)
            {
                Voice.getInstance();
            }

            if (useHandCursor)
            {
                cursor = HandCursor.getInstance();
                DispatcherTimer updateHandCursorTimer = new DispatcherTimer();
                updateHandCursorTimer.Interval = TimeSpan.FromMilliseconds(100);
                updateHandCursorTimer.Tick += new EventHandler(updateHandCursorTimerTick);
                updateHandCursorTimer.Start();
            }

        }

        public void sleep()
        {
            if (!currentPage().Name.Equals(screenSaver.Name)) {
                pushPage(screenSaver);
            }
        }

        DispatcherTimer sleepTimer;

        public void restartSleepTimer()
        {
            if (sleepTimer != null)
            {
                sleepTimer.Stop();
                sleepTimer.Start();
            }
            else
            {
                sleepTimer = new DispatcherTimer();
                sleepTimer.Interval = TimeSpan.FromMilliseconds(sleepTimerAmount);
                sleepTimer.Tick += new EventHandler(sleepTimerTick);
                sleepTimer.Start();
            }
        }

        private void sleepTimerTick(Object sender, EventArgs e)
        {
            sleepTimer.Stop();
            sleep();
        }

        Rectangle shade;

        private void initCanvases()
        {
            mainCanvas = new Canvas();
            mainCanvas.Name = "mainCanvas";

            this.Content = mainCanvas;

            bgCanvas = new BackgroundCanvas();
            bgCanvas.setBackground(Properties.Resources.blackspotlight);
            mainCanvas.Children.Add(bgCanvas);

            pageParentCanvas = new Canvas();
            pageParentCanvas.Name = "pageParentCanvas";
            mainCanvas.Children.Add(pageParentCanvas);

            shade = new Rectangle();
            shade.Width = GlobalSettings.BG_WIDTH;
            shade.Height = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height;//120;
            mainCanvas.Children.Add(shade);
            shade.Fill = new SolidColorBrush(GlobalSettings.BannerColor);

            Canvas.SetTop(shade, 0);
            Canvas.SetLeft(shade, GlobalSettings.WHITESPACESIDES);

            NavigationPage np = NavigationPage.getInstance();
        }

        private void initTime()
        {
            
            /*
            Rectangle rbody = new Rectangle();
            rbody.Width = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width - whiteSpaceSides * 2;
            rbody.Height = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height - r.Height - 2 * whiteSpaceTopBottom;
            mainCanvas.Children.Add(rbody);
            rbody.Fill = new SolidColorBrush(GlobalSettings.BannerColor);

            Canvas.SetTop(rbody, Canvas.GetTop(r) + r.Height + whiteSpaceTopBottom);
            Canvas.SetLeft(rbody, whiteSpaceSides);
             */

            dayLabel = new Label();
            mainCanvas.Children.Add(dayLabel);
            Canvas.SetTop(dayLabel, -10);

            dayLabel.Foreground = new SolidColorBrush(GlobalSettings.TextColor);
            dayLabel.FontSize = 40;

            timeLabel = new Label();
            mainCanvas.Children.Add(timeLabel);
            Canvas.SetTop(timeLabel, 25);

            timeLabel.Foreground = new SolidColorBrush(GlobalSettings.TextColor);
            timeLabel.FontSize = 70;

            DispatcherTimer timeTimer = new DispatcherTimer();
            timeTimer.Interval = TimeSpan.FromSeconds(1);
            timeTimer.Tick += new EventHandler(updateTime);
            timeTimer.Start();
        }

        public void updateTime(Object sender, EventArgs e)
        {

            //Canvas.SetLeft(ellipseC, contentCanvas.ActualWidth / 2 - ellipseC.Width / 2);
            //Canvas.SetTop(ellipseC, contentCanvas.ActualHeight / 2 - ellipseC.Height / 2);
            //Canvas.SetZIndex(ellipseC, 100);

            //timeLabel.Visibility = System.Windows.Visibility.Hidden;

            DateTime dateValue = DateTime.Now;
            // Console.WriteLine(dateValue.ToString("dddd"));    // Displays Wed

            this.dayLabel.Content = dateValue.ToString("dddd MMMM d");//DateTime.Now.ToLocalTime();
            this.timeLabel.Content = dateValue.ToString("h:mm tt");
            // need to rerender to get updated width
            dayLabel.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
            timeLabel.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
            Canvas.SetLeft(dayLabel, System.Windows.SystemParameters.PrimaryScreenWidth / 2 - dayLabel.ActualWidth / 2);
            Canvas.SetLeft(timeLabel, System.Windows.SystemParameters.PrimaryScreenWidth / 2 - timeLabel.ActualWidth / 2);
            // timeLabel.Visibility = System.Windows.Visibility.Visible;

        }

        private void initPages()
        {
            Console.WriteLine(Properties.Resources.ResourceManager.BaseName);

            screenSaver = new ScreenSaverUIPage();

            SlidingTileUIPage rootPage = new SlidingTileUIPage("Home", null);
            rootPage.isHomeButtonVisible = false;
            rootPage.isBackButtonVisible = false;

            //SlidingPathUIPage blah = new SlidingPathUIPage("Blah", Util.getBitmapSource(Properties.Resources.communicate));

            SlidingTileUIPage entertainPage = new SlidingTileUIPage("Entertainment", Util.getBitmapSource(Properties.Resources.icon_tv2));
            SlidingTileUIPage newsPage = new SlidingTileUIPage("News", Util.getBitmapSource(Properties.Resources.icon_info1));
            AnatomyUIPage anatomyPage = new AnatomyUIPage();

            //SlidingIconUIPage settingsPage = new SlidingIconUIPage("Settings", Util.getBitmapSource(Properties.Resources.icon_info1));

            SlidingTileUIPage languagePage = new SlidingTileUIPage("Language", Util.getBitmapSource(Properties.Resources.language));
            languagePage.addUIOption(new LanguageUIOption("English", "en", Util.getBitmapSource(Properties.Resources.uk_great_britain1)));
            languagePage.addUIOption(new LanguageUIOption("French", "fr", Util.getBitmapSource(Properties.Resources.france1)));
            languagePage.addUIOption(new LanguageUIOption("Italian", "it", Util.getBitmapSource(Properties.Resources.italy1)));
            languagePage.addUIOption(new LanguageUIOption("German", "de", Util.getBitmapSource(Properties.Resources.germany2)));
            languagePage.addUIOption(new LanguageUIOption("Polish", "pl", Util.getBitmapSource(Properties.Resources.poland1)));
            languagePage.addUIOption(new LanguageUIOption("Spanish", "es", Util.getBitmapSource(Properties.Resources.spain1)));

            //settingsPage.addUIOption(languagePage);

            if (GlobalSettings.isUsingKinect)
            {
                CalibrateKinectUIPage cp = new CalibrateKinectUIPage();
                cp.areQuickButtonsVisible = false;
                cp.areShiftButtonsVisible = false;
                //settingsPage.addUIOption(cp);
            }

            SlidingTileUIPage themePage = new SlidingTileUIPage("Photos", Util.getBitmapSource(Properties.Resources.photos));
            //themePage.addUIOption(new SlideshowUIPage("Basic", Util.getBitmapSource(Properties.Resources.icon_info1), SlideshowUIPage.getSimpleTheme()));
            themePage.addUIOption(new SlideshowUIPage("Nature", Util.getBitmapSource(Properties.Resources.icon_info1), SlideshowUIPage.getNatureTheme()));
            themePage.addUIOption(new SlideshowUIPage("My Photos", Util.getBitmapSource(Properties.Resources.icon_info1), SlideshowUIPage.getIconTheme()));

            inbox = new InboxUIPage();

            SkypeMessageListUI helpPage = new SkypeMessageListUI("Call Nurse", GlobalSettings.nurseSkypeID, SkypeMessageListUI.getStandardHelpOptions(), Util.getBitmapSource(Properties.Resources.icon_nurse));
            helpPage.isNurseButtonVisible = false;
            help = helpPage;

            SkypeContactListUI audioChatPage = new SkypeContactListUI("Phone", Util.getBitmapSource(Properties.Resources.call), Hugo.UIPages.SkypeContactListUI.SkypeAction.Call);
            SkypeContactListUI textChatPage = new SkypeContactListUI("Text", Util.getBitmapSource(Properties.Resources.text), Hugo.UIPages.SkypeContactListUI.SkypeAction.Message);
            textChatPage.addMessageOptions(SkypeMessageListUI.getStandardMessageOptions());

            SlidingTileUIPage moviePage = new SlidingTileUIPage("Movies", Util.getBitmapSource(Properties.Resources.film));
            moviePage.addUIOption(new MovieUIOption("Chimpanzee", Util.getBitmapSource(Properties.Resources.Chimpanzee), "C:\\Lorax.mov"));
            moviePage.addUIOption(new MovieUIOption("Lorax", Util.getBitmapSource(Properties.Resources.Lorax), "C:\\Lorax.mov"));
            moviePage.addUIOption(new MovieUIOption("Mirror Mirror", Util.getBitmapSource(Properties.Resources.Mirror_Mirror), "C:\\Lorax.mov"));
            moviePage.addUIOption(new MovieUIOption("Titanic", Util.getBitmapSource(Properties.Resources.Titanic), "C:\\Lorax.mov"));

            //SlidingTileUIPage gamesPage = new SlidingTileUIPage("Games", Util.getBitmapSource(Properties.Resources.games));

                MemoryGamePage mgp = new MemoryGamePage();
                //gamesPage.addUIOption(new CanvasWrapperUIPage("Memory", Util.getBitmapSource(Properties.Resources.memory), mgp));

                SlidingTileUIPage backgroundPage = new SlidingTileUIPage("Backgrounds", Util.getBitmapSource(Properties.Resources.photos));
            backgroundPage.addUIOption(new BackgroundUIOption("Plain", Properties.Resources.blackspotlight));
            backgroundPage.addUIOption(new BackgroundUIOption("Beach", Properties.Resources.beachbg));
            backgroundPage.addUIOption(new BackgroundUIOption("Water", Properties.Resources.waterbg));
            backgroundPage.addUIOption(new BackgroundUIOption("Space", Properties.Resources.cooliris_bg));
            
                
            rootPage.addUIOption(help);
            rootPage.addUIOption(audioChatPage);
            rootPage.addUIOption(textChatPage);
            //rootPage.addUIOption(inbox);
            rootPage.addUIOption(themePage);
            rootPage.addUIOption(moviePage);
            rootPage.addUIOption(new CanvasWrapperUIPage("Memory", Util.getBitmapSource(Properties.Resources.memory), mgp));
            //rootPage.addUIOption(mgp);
            rootPage.addUIOption(anatomyPage);
            rootPage.addUIOption(languagePage);
            rootPage.addUIOption(backgroundPage);
            root = rootPage;
            

            pushPage(root);

        }

        static NotificationUIPage currentNotification = null;


        public void respondToKey(Object sender, KeyEventArgs e)
        {
            
                if (!masterRespondToKey(e))
                {
                    if (!currentPage().respondToKey(e))
                    {
                        if (!NavigationPage.getInstance().respondToKey(e))
                        {
                            return;
                        }
                    }
                    HandCursor.getInstance().setHovering(true);
                }
            
            
        }

        public void respondToClick(MouseButtonEventArgs e)
        {
            if (!currentPage().respondToClick(e))
            {
                if (!NavigationPage.getInstance().respondToClick(e))
                {
                    return;
                }
            }
            HandCursor.getInstance().setHovering(false);
        }

        public void setCursorPositionMaster(Point p)
        {
            if (!currentPage().overridesHandCursor)
            {
                if (!currentPage().setCursorPosition(p))
                {
                    if (!NavigationPage.getInstance().setCursorPosition(p))
                    {
                        HandCursor.getInstance().setHovering(false);
                        return;
                    }
                }
                HandCursor.getInstance().setHovering(true);
            }
            else
            {
                NavigationPage.getInstance().setCursorPosition(p);
            }
        }

        /// Events
        /// 
        public bool masterRespondToKey(KeyEventArgs e)
        {
            if (this.currentPage().Name.Equals(screenSaver.Name))
            {
                popPage();
                return true;
            }
            else
            {
                restartSleepTimer();
            }

            if (e.Key == Key.H)
            {
                pushPage(help);
                return true;
            }
            if (e.Key == Key.N)
            {
                //if (currentNotification == null)
                //{
                List<UIOption> options = new List<UIOption>();
                options.Add(new TileUIPage("SkypeCall", Hugo.Util.getBitmapSource(Properties.Resources.icon_skypecontact)));
                // should pass a function or event handler
                NotificationUIPage p = new NotificationUIPage("Andrea sent you a message", "Incoming call from blah. Incoming call from blah. Incoming call from blah. Incoming call from blah. Incoming call from blah. Incoming call from blah. ", options);
                enqueueNotification(p);
                //}
                //else
                //{
                //    popCurrentNotification;
                //}
                return true;
            }
            else
            {
                if (notificationQueue.Count > 0)
                {
                    notificationQueue.Peek().respondToKey(e);
                    return true;
                }
            }

            return false;
        }

        /// Page Control
        /// 
        static int notificationTimeout = 3000;

        public static void enqueueNotification(NotificationUIPage p)
        {
            Sounds.playSound(Sounds.Sound.Notification);
            notificationQueue.Enqueue(p);

            showNextNotificationIfPossible();
        }

        private static void showNextNotificationIfPossible()
        {
            if (currentNotification != null || notificationQueue.Count == 0) { return; }

            currentNotification = notificationQueue.Peek();

            NotificationUIPage p = currentNotification;
            p.setPage();

            DispatcherTimer _timer = new DispatcherTimer();
            _timer.Interval = TimeSpan.FromMilliseconds(notificationTimeout);
            _timer.Tick += new EventHandler(notificationTimerElapsed);
            _timer.Start();
        }

        static void notificationTimerElapsed(object sender, EventArgs e)
        {
            //we want this event handler executed just once
            DispatcherTimer thisTimer = (DispatcherTimer)sender;
            thisTimer.Stop();

            dequeueCurrentNotification();
        }

        private static void dequeueCurrentNotification()
        {
            if (currentNotification == null) { return; }

            currentNotification.unSetPage();
            notificationQueue.Dequeue();

            currentNotification = null;
            showNextNotificationIfPossible();
        }

        public UIPage getCurrentPage()
        {
            return pageStack.Peek();
        }

        public static void pushPage(UIPage p)
        {
            if (pageStack.Count > 0)
            {
                pageStack.Peek().unSetPage();
            }
           
            pageStack.Push(p);
            p.setPage();


            if (GlobalSettings.isBlind)
            {
                Sounds.speakMessageAsync(p.Name);
            }
            //Sounds.speakMessage(p.Name);
        }

        internal static void popAllPages()
        {
            pageStack.Peek().unSetPage();

            while (pageStack.Peek() != root)
            {
                pageStack.Pop();
            }

            root.setPage();
        }

        internal static void popPage()
        {
            if (pageStack.Count == 1)
            {
                Console.WriteLine("Can't leave the root");
                return;
            }

            if (GlobalSettings.isBlind)
            {
                Sounds.speakMessageAsync(pageStack.Peek().Name);
            }
            else
            {
                Sounds.playSound(Sounds.Sound.Accept);
            }

            Console.WriteLine("Leaving page " + pageStack.Peek().Name);
            pageStack.Pop().unSetPage();

            Console.WriteLine("Reshowing page " + pageStack.Peek().Name);
            pageStack.Peek().setPage();


            if (GlobalSettings.isBlind)
            {
                Sounds.speakMessageAsync(pageStack.Peek().Name);
            }
            else
            {
                Sounds.playSound(Sounds.Sound.Navigate);
            }
            
        }

        private UIPage currentPage()
        {
            return pageStack.Peek();
        }

        internal static void showInbox()
        {
            //pushPage(inbox);
        }

        internal static void callNurse()
        {
            pushPage(help);
        }

        internal void hideShade()
        {
            shade.Opacity = 0;
        }

        internal void showShade()
        {
            shade.Opacity = 1;
        }


        internal static void removePage(UIPage page)
        {
            Stack<UIPage> newPageStack = new Stack<UIPage>();
            foreach (UIPage p in pageStack)
            {
                if (p != page)
                {
                    newPageStack.Push(p);
                } 
            }

            pageStack = newPageStack;

            page.silentUnset();
        }
    }
}
